home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
ALLOC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-03
|
8KB
|
389 lines
/* memory allocation routines
*
* Adapted from alloc routine in K&R; memory statistics and interrupt
* protection added for use with net package.
*/
#include <stdio.h>
#if (defined(MSC) || defined(__TURBOC__))
# include <alloc.h>
#else
# ifdef M_XENIX
# include <prototypes.h>
# else
extern char *sbrk();
extern int brk();
# endif
#endif
#include "global.h"
#include "alloc.h"
static long grabbedbytes = 0;
static unsigned memfail = 0;
static HEADER base = {&base,1};
HEADER PTR allocp = &base;
int need_disable = 0;
/* Define ALLOCDEBUG for allocation recording. Note: works only with
* small memory model
*/
#ifdef ALLOCDEBUG
#define NALLOC 150
/* Map of allocated memory chunks */
struct alloc {
char *addr;
unsigned size;
long pc;
};
struct alloc alloc[NALLOC];
#endif
/* Allocate block of 'nb' bytes */
#ifdef MSDOS
void *
#else
char *
#endif
malloc(nb)
unsigned nb;
{
HEADER PTR morecore();
register HEADER PTR p, PTR q;
register unsigned nu;
#ifdef ALLOCDEBUG
struct alloc *ap;
unsigned short *ptr;
#endif
#ifndef NODISABLE
char i_state;
if (need_disable)
i_state = disable();
#endif
/* Round up to full block, incl hdr */
nu = (nb + 2 * sizeof(HEADER) - 1) / sizeof(HEADER);
if ((q = allocp) == NULLHDR){
base.s.ptr = allocp = q = &base;
base.s.size = 1;
}
for (p = q->s.ptr; ; q = p, p = p->s.ptr){
if (p->s.size >= nu){
/* This chunk is at least as large as we need */
if (p->s.size == nu){
/* Perfect fit; remove from list */
q->s.ptr = p->s.ptr;
} else {
/* Carve out piece from end of entry */
p->s.size -= nu;
p += p->s.size;
p->s.size = nu;
}
allocp = q;
p->s.ptr = p; /* for auditing */
#ifdef ALLOCDEBUG
for(ap = alloc;ap < &alloc[NALLOC];ap++){
if(ap->addr == NULLCHAR){
ap->addr = (char *)(p+1);
ap->size = nb;
ptr = &nb;
#ifdef LARGECODE
ap->pc = (long)ptr[-1] << 16 +
(long)ptr[-2];
#else
ap->pc = (long)ptr[-1];
#endif
break;
}
}
#endif
#ifndef NODISABLE
if (need_disable)
restore(i_state);
#endif
return (char *)(p + 1);
}
if (p == allocp && (p = morecore(nu)) == NULLHDR){
memfail++;
#ifndef NODISABLE
if (need_disable)
restore(i_state);
#endif
return NULLCHAR;
}
}
}
/* Put memory block back on heap */
void
free(blk)
#ifdef MSDOS
void *blk;
#else
char *blk;
#endif
{
register HEADER PTR p, PTR q;
unsigned short *ptr;
#ifdef ALLOCDEBUG
struct alloc *ap;
#endif
#ifndef NODISABLE
char i_state;
#endif
if (blk == NULL)
return;
#ifndef NODISABLE
if (need_disable)
i_state = disable();
#endif
#ifdef ALLOCDEBUG
for(ap = alloc;ap < &alloc[NALLOC];ap++){
if(ap->addr == blk){
ap->addr = NULLCHAR;
break;
}
}
#endif
p = (HEADER PTR)blk - 1;
/* Audit check */
if(p->s.ptr != p){
ptr = (unsigned short *)&blk;
printf("WARNING!! freeing garbage (0x%lx) pc = 0x%04x %04x\n",
ptr2long(blk),ptr[-1],ptr[-2]);
fflush(stdout);
#ifndef NODISABLE
if (need_disable)
restore(i_state);
#endif
#ifdef Z80
printf("SP = 0x%04x\n",getsp());
for(;;) ;
#else
return;
#endif
}
/* Search the free list looking for the right place to insert */
for(q = allocp; !(p > q && p < q->s.ptr); q = q->s.ptr){
/* Highest address on circular list? */
if(q >= q->s.ptr && (p > q || p < q->s.ptr))
break;
}
if(p + p->s.size == q->s.ptr){
/* Combine with front of this entry */
p->s.size += q->s.ptr->s.size;
p->s.ptr = q->s.ptr->s.ptr;
} else {
/* Link to front of this entry */
p->s.ptr = q->s.ptr;
}
if(q + q->s.size == p){
/* Combine with end of this entry */
q->s.size += p->s.size;
q->s.ptr = p->s.ptr;
} else {
/* Link to end of this entry */
q->s.ptr = p;
}
allocp = q;
#ifndef NODISABLE
if (need_disable)
restore(i_state);
#endif
}
/* Move existing block to new area */
#ifdef MSDOS
void *
#else
char *
#endif
realloc(area,size)
#ifdef MSDOS
void *area;
#else
char *area;
#endif
unsigned size;
{
unsigned osize;
HEADER PTR hp;
char *cp;
#ifndef NODISABLE
/* Make sure nobody else comes in and takes it */
char i_state;
if (need_disable)
i_state = disable();
#endif
hp = (HEADER PTR)area - 1;
osize = (hp->s.size -1) * sizeof(HEADER);
free(area);
if((cp = malloc(size)) != NULLCHAR && cp != area)
memcpy((char *)cp,(char *)area,size>osize? osize : size);
#ifndef NODISABLE
if (need_disable)
restore(i_state);
#endif
return cp;
}
/* Allocate block of cleared memory */
#ifdef MSDOS
void *
#else
char *
#endif
calloc(nelem,size)
unsigned nelem; /* Number of elements */
unsigned size; /* Size of each element */
{
register unsigned i;
register char *cp;
#ifdef ALLOCDEBUG
struct alloc *ap;
short *ptr;
#endif
i = nelem * size;
if((cp = malloc(i)) != NULLCHAR)
memset(cp,0,i);
#ifdef ALLOCDEBUG
if(cp == NULLCHAR)
return cp;
/* Adjust caller field to indicate real caller, not calloc() */
ptr = (short *)&nelem;
for(ap = alloc; ap < &alloc[NALLOC];ap++)
if(ap->addr == cp)
ap->pc = (long)ptr[-1];
#endif
return cp;
}
/* Get more memory from the system and put it on the heap */
HEADER PTR
morecore(nu)
unsigned nu;
{
register char *cp;
register HEADER PTR up;
/* adjust requests for small amounts upward to MIN_ALLOC */
/* when LARGEDATA, make sure we have one unit extra */
if (nu < (MIN_ALLOC / sizeof(HEADER)))
nu = MIN_ALLOC / sizeof(HEADER)
#ifdef LARGEDATA
+ 1;
else
nu++
#endif
;
if ((int)(cp = sbrk(nu * sizeof(HEADER))) == -1)
return NULLHDR;
grabbedbytes += nu * sizeof(HEADER);
#ifdef LARGEDATA
/* most C runtimes don't like pointers with offset 0! */
if ((FP_OFF(cp) % sizeof(HEADER)) == 0){
cp += 4; /* so move it off the para mark */
nu--; /* which costs us one unit */
}
#endif
up = (HEADER PTR)cp;
up->s.size = nu;
up->s.ptr = up; /* satisfy audit */
free((char *)(up + 1));
return allocp;
}
/* Grab as much memory as possible from the system and put it on the heap */
void
grabcore()
{
char *cp;
register HEADER PTR up;
register unsigned long size;
#if (defined(MSC) || defined(__TURBOC__))
char redzone[4096];
#endif
/* Find out where the break is */
cp = sbrk(0);
/* Now try to push it as high as possible */
#if (defined(MSC) || defined(__TURBOC__))
redzone[0] = size = 0;
while(sbrk(256) != (char *)(-1)) {
size += 256;
# ifdef LARGEDATA
if (size > 32000)
break;
# endif
}
#else
for(size=256; size < 65535-256;size += 256){
if(brk((char *) (cp + size)) == -1){
size -= 256;
break;
}
}
#endif
grabbedbytes += size;
#ifdef LARGEDATA
/* most C runtimes don't like pointers with offset 0! */
if ((FP_OFF(cp) % sizeof(HEADER)) == 0){
cp += 4; /* so move it off the para mark */
size -= 4;
}
#endif
up = (HEADER PTR)cp;
up->s.size = size / sizeof(HEADER);
up->s.ptr = up; /* satisfy audit */
free((char *)(up + 1));
}
#ifndef NOMEMSTAT
/* Print free list map */
memstat(argc,argv)
int argc;
char *argv[];
{
HEADER PTR p;
unsigned long totalfree;
totalfree = 0;
p = &base;
do {
totalfree += (unsigned long) p->s.size * sizeof(HEADER);
if (argc != 1){
printf("%*lx %lu",2*sizeof(p),ptr2long(p),
(unsigned long) p->s.size * sizeof(HEADER));
if(p == allocp)
printf(" <-- allocp\n");
else
printf("\n");
}
p = p->s.ptr;
} while(p != &base);
printf("Total: %lu bytes grabbed, %lu bytes free\n",
grabbedbytes,totalfree);
#ifdef ALLOCDEBUG
if (argc != 1) {
struct alloc *ap;
printf("addr size caller\n");
for(ap = alloc;ap < &alloc[NALLOC];ap++){
if(ap->addr != NULLCHAR)
printf("0x%-8lx%-10d %08lx\n",
ptr2long(ap->addr),ap->size,ap->pc);
}
}
#endif
printf("malloc fails %u\n",memfail);
fflush(stdout);
return 0;
}
#endif